﻿using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using InformaticaDiary.Common;

namespace InformaticaDiaryWin
{
    public class Informatica
    {
        [DllImport("user32.dll")]
        private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]
        private static extern int SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern int IsIconic(IntPtr hWnd);
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            if (!Informatica.IsSingleInstance())
            {
                Console.WriteLine("More than one instance"); // Exit program.
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            ExceptionLogger.ApplicationStartupPath = Application.StartupPath;
            try
            {
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                //IBusinessLogic _BusinessLogic = new BusinessLogic();
                if (IsApplicationAlreadyRunning())
                {
                    SwitchToCurrentInstance();
                    return;
                }               
                Assembly UIAssembly;
                UIAssembly = Assembly.LoadFrom("InformaticaDiaryUI.dll");
                Form LoginForm = (Form)UIAssembly.CreateInstance("InformaticaDiary.InformaticaDiaryUI.MainForm");
                //((IBusinessLogicConsumer)LoginForm).IBusinessLogic = _BusinessLogic;

                DialogResult dr = LoginForm.ShowDialog();

                if (dr == DialogResult.Retry)
                {
                    Form ChangePasswordForm = (Form)UIAssembly.CreateInstance("InformaticaDiary.InformaticaDiaryUI.ChangePassword");
                    //((IBusinessLogicConsumer)ChangePasswordForm).IBusinessLogic = _BusinessLogic;
                    DialogResult cdr = ChangePasswordForm.ShowDialog();
                    if (cdr == DialogResult.Cancel)
                    {
                        Environment.Exit(Environment.ExitCode);
                    }

                }
                else if (dr == DialogResult.Cancel)
                {
                    Environment.Exit(Environment.ExitCode);
                }

                LoginForm.Close();

                Form ActivatedForm = null;

                ActivatedForm = (Form)UIAssembly.CreateInstance("TeaBoard.Buyer.UI.MainForm");
               // ((IBusinessLogicConsumer)ActivatedForm).IBusinessLogic = _BusinessLogic;

                Application.Run(ActivatedForm);
            }
            catch (AccessViolationException ex)
            {
                ExceptionLogger.WriteUIError("Main()," + ex.Message);
            }
            catch (ApplicationException ex)
            {                
                ExceptionLogger.WriteUIError("Main()," + ex.Message);
            }
            catch (Exception ex)
            {               
                ExceptionLogger.WriteUIError("Main()," + ex.Message);
            }
        }

        static Mutex _m;

        static bool IsSingleInstance()
        {
            try
            {
                // Try to open existing mutex.
                Mutex.OpenExisting("INFORMATICA");
            }
            catch
            {
                // If exception occurred, there is no such mutex.
                Informatica._m = new Mutex(true, "INFORMATICA");

                // Only one instance.
                return true;
            }
            // More than one instance.
            return false;
        }


        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs t)
        {
            //MessageBox.Show("Application_ThreadException Message : " + t.Exception.Message + " StackTrace : " + t.Exception.StackTrace);
            ExceptionLogger.WriteUIError("Main(),", t.Exception);
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            //MessageBox.Show("CurrentDomain_UnhandledException Message : " + ((Exception)e.ExceptionObject).Message + " StackTrace : " + ((Exception)e.ExceptionObject).StackTrace);
            ExceptionLogger.WriteUIError("Main(),", (Exception)e.ExceptionObject);
        }
        /// <summary>
        /// SwitchToCurrentInstance
        /// </summary>
        private static void SwitchToCurrentInstance()
        {
            IntPtr hWnd = GetCurrentInstanceWindowHandle();
            if (hWnd != IntPtr.Zero)
            {
                // Restore window if minimised. Do not restore if already in
                // normal or maximised window state, since we don't want to
                // change the current state of the window.
                if (IsIconic(hWnd) != 0)
                {
                    ShowWindow(hWnd, SW_RESTORE);
                }

                // Set foreground window.
                SetForegroundWindow(hWnd);
            }
        }
        static bool IsApplicationAlreadyRunning()
        {
            string proc = Process.GetCurrentProcess().ProcessName;
            Process[] processes = Process.GetProcessesByName(proc);
            if (processes.Length > 1)
                return true;
            else
                return false;
        }
        /// <summary>
        /// GetCurrentInstanceWindowHandle
        /// </summary>
        /// <returns></returns>
        private static IntPtr GetCurrentInstanceWindowHandle()
        {
            IntPtr hWnd = IntPtr.Zero;
            Process process = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(process.ProcessName);
            foreach (Process _process in processes)
            {
                // Get the first instance that is not this instance, has the
                // same process name and was started from the same file name
                // and location. Also check that the process has a valid
                // window handle in this session to filter out other user's
                // processes.
               
                // &&
                 //   _process.MainModule.FileName == process.MainModule.FileName &&
                //    _process.MainWindowHandle != IntPtr.Zero
                 //
                
                if (_process.Id != process.Id )
                {
                    hWnd = _process.MainWindowHandle;
                    break;
                }
            }
            return hWnd;
        }
        const int SW_RESTORE = 9;

    }

}